package com.airlines.crewassignment.service.crew.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.airlines.common.ListSortUtil;
import com.airlines.common.MD5Util;
import com.airlines.common.StringToListUtil;
import com.airlines.crewassignment.constant.RuleConstant;
import com.airlines.crewassignment.dao.CrewMapper;
import com.airlines.crewassignment.dao.FlightInfoMapper;
import com.airlines.crewassignment.dao.LinkLineMapper;
import com.airlines.crewassignment.domain.Crew;
import com.airlines.crewassignment.domain.CrewFlightExperience;
import com.airlines.crewassignment.domain.DateTimeRange;
import com.airlines.crewassignment.domain.FlightInfo;
import com.airlines.crewassignment.domain.LinkLine;
import com.airlines.crewassignment.domain.util.DutyDurationUtil;
import com.airlines.crewassignment.entity.ValueForDate;
import com.airlines.crewassignment.entity.basicinfo.Foundation;
import com.airlines.crewassignment.entity.basicinfo.OvernightAirport;
import com.airlines.crewassignment.service.basicinfo.FoundationService;
import com.airlines.crewassignment.service.basicinfo.OvernightAirportService;
import com.airlines.crewassignment.service.crew.CrewFlightExperienceService;
import com.airlines.crewassignment.service.linkline.FlightInfoService;
import com.airlines.crewassignment.service.linkline.LinkLineService;
import com.airlines.crewassignment.service.linkline.TaskLoopFlightFactService;

/**
 * @author xxxx
 * @date 2018年4月4日 
 * @description
 */
@Service
public class CrewFlightExperienceServiceImpl implements CrewFlightExperienceService	{
	@Autowired
	private FlightInfoMapper flightInfoMapper;
	@Autowired
	private CrewMapper crewMapper;
	@Autowired
	private LinkLineMapper linkLineMapper;
	@Autowired
	private LinkLineService linkLineService;
	@Autowired
	private FlightInfoService flightInfoService;
	@Autowired
	private OvernightAirportService overnightAirportService;
	@Autowired
	private TaskLoopFlightFactService taskLoopFlightFactService;
	@Autowired
	private FoundationService foundationService;
	@Override
	public List<FlightInfo> listFlightInfoForCrew(DateTimeRange dateTimeRange, String workcode,String dutyCode) {
		//从FOC获取数据
		List<FlightInfo> list = flightInfoMapper.listFlightInfoForCrew(dutyCode,dateTimeRange, workcode);
		//从QAR获取数据并组装,暂时不做
	
		//计算每个航段的飞行时间
		for(FlightInfo  f : list){
			int flightDuration  =flightInfoService.getFlightDuration(f);
			f.setFlightDuration(flightDuration);
		}
		
		return list;
	}
	@Override
	public int flightDurationSum(DateTimeRange dateTimeRange, String workcode) {
		List<FlightInfo>  list = this.listFlightInfoForCrew(dateTimeRange, workcode,null);

		int flightDurationSum =  0;
		for(FlightInfo  f: list){
			flightDurationSum += f.getFlightDuration();
		}
		
		return flightDurationSum;
	}
	
	@Override
	public DateTimeRange getFlightDateRangeMonth(Date beforeFlightDate) {
		DateTime start = new DateTime(beforeFlightDate).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
		DateTime end = new DateTime(beforeFlightDate).minus(1).millisOfDay().withMaximumValue();
		return new DateTimeRange(start.toDate(),end.toDate());
	}
	@Override
	public DateTimeRange getFlightDateRangeYear(Date beforeFlightDate) {
		DateTime start = new DateTime(beforeFlightDate).dayOfYear().withMinimumValue().withTimeAtStartOfDay();
		DateTime end = new DateTime(beforeFlightDate).minus(1).millisOfDay().withMaximumValue();
		return new DateTimeRange(start.toDate(),end.toDate());
	}
	
	@Override
	public Map<String,String> listCrewLastAirport(String dutyCode,Date beforeFlightDate) {
		Date StartDate = new DateTime(beforeFlightDate).minusDays(30).toDate();
		Date endDate = new DateTime(beforeFlightDate).minusDays(1).toDate();
		DateTimeRange dr = new DateTimeRange(StartDate,endDate);
		List<CrewFlightExperience> list = crewMapper.listCrewLastAirport(dutyCode,null,dr);
		Map<String,String> map = new HashMap<>();
		for(CrewFlightExperience c : list){
			map.put(c.getWorkcode(), c.getLastAirport());
		}
		
		return map;
	}
	@Override
	public List<LinkLine> listLinkLineBaseForCrew(String dutyCode,DateTimeRange dateTimeRange, String workcode) {
		return linkLineMapper.listLinkLineBaseByWorkcode(dutyCode,dateTimeRange, workcode);
	}
	
	@Override
	public Map<String,Integer> listNightPassCount(String dutyCode,DateTimeRange dateTimeRange) {
		Map<String,Integer> map = new HashMap<>();
		
		//从FOC获取数据	
		List<FlightInfo> flightInfoList = flightInfoMapper.listFlightInfoForCrew(dutyCode,dateTimeRange, null);
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, null);
		List<Foundation> baseList  = foundationService.list(dutyCode);
		
		for(Crew crew : crewList){
			String workcode = crew.getWorkcode();
			List<FlightInfo> flightInfoListForCrew = new ArrayList<>();
			for(FlightInfo f : flightInfoList){
				String workcodes = f.getCrewWorkcodes();
				if(inWorkcodes(workcodes,workcode)){
					flightInfoListForCrew.add(f);
				}
			}
			
			int nightPassCount = this.getNightPassCount(flightInfoListForCrew,baseList);
			
		
			map.put(workcode, nightPassCount);
		}
		return map;
	}

	/**
	 * 从航班中获取过夜次数
	 * @param flightInfoList
	 * @return
	 */
	private int getNightPassCount(List<FlightInfo> flightInfoList,List<Foundation> baseList){
		Set<LinkLine> linkLineSet = new HashSet<>();
		
		ListSortUtil.sort(flightInfoList, true, "sta");
		for(FlightInfo f : flightInfoList){
			LinkLine l  = new LinkLine();
			l.setFlightDate(f.getFlightDate());
			l.setCrewLinkLineKey(MD5Util.md5Encode(l.getFlightDate().toString())); //利用主键，组装Set计划
			linkLineSet.add(l);
		}
		
		//按照每日组装连线，不管 crewLinkLineNo
		for(LinkLine l : linkLineSet){
			for(FlightInfo f : flightInfoList){
				if(l.getFlightDate().equals(f.getFlightDate())){
					l.getFlightInfoList().add(f);
				}
			}
			int flightInfoListSize = l.getFlightInfoList().size();
			if(flightInfoListSize>0){
				l.setLinkArrivalAirport(l.getFlightInfoList().get(flightInfoListSize-1).getArrivalAirport());
			}
		}
		
		//计算连线过夜次数
		int nightPassCount = 0;
		for(LinkLine l : linkLineSet){
			String linkArrivalAirport = l.getLinkArrivalAirport();
			for(Foundation f : baseList){
				if(StringUtils.equals(linkArrivalAirport, f.getBase())){
					nightPassCount ++;
				}
			}
//			if(airportIsNightPass(linkArrivalAirport)){
//				nightPassCount ++;
//			}
		}
		
		return nightPassCount;
	}

	/**
	 * 判断是否是过夜
	 */
	public boolean airportIsNightPass(String airport){
		OvernightAirport o  = overnightAirportService.get(airport);
		if(o == null){
			return false;
		}
		
		if(o.getIsDelete() == 1){
			return false;
		}
		return true;
	}

	@Override
	public void initDutyDurationBeforeDay(String dutyCode,List<Crew> crewList, DateTime start, DateTime end) {

		//1.根据日期范围查询连线信息
		List<LinkLine> linkLines = linkLineMapper.listLinkLineBaseByWorkcode(dutyCode,new DateTimeRange(start,end),null);

		//2.查询每个人的连线信息
		for(Crew crew : crewList){
			String workcode = crew.getWorkcode();
			Map<DateTime,List<LinkLine>> crewLinkLineMap = new HashMap<>();//每天的连线
			for(LinkLine l : linkLines){
				String workcodes = l.getCrewWorkcodes();
				if(inWorkcodes(workcodes,workcode)){
					DateTime flightDateTime = new DateTime(l.getFlightDate());
					List<LinkLine> tempList = crewLinkLineMap.get(flightDateTime);
					if(tempList == null){
						tempList = new ArrayList<>();
						crewLinkLineMap.put(flightDateTime,tempList);
					}
					tempList.add(l);
				}
			}

			List<ValueForDate> crewDateDutys = new ArrayList<>();
			for(DateTime temp = start; !temp.isAfter(end) ;temp = temp.plusDays(1)){
				ValueForDate vfd = new ValueForDate();
				vfd.setDateTime(temp);
				vfd.setValue(DutyDurationUtil.getDutyDurationByLinkLine(crewLinkLineMap.get(temp)));
				crewDateDutys.add(vfd);
			}
			crew.getCrewFlightExperience().setDutyDurationList(crewDateDutys);
		}
	}

	private boolean inWorkcodes(String workcodes,String workcode){
		List<String> workcodeList = StringToListUtil.getListDefault(workcodes);
		for(String w : workcodeList){
			if(StringUtils.equals(w, workcode)){
				return true;
			}
		}
		
		return false;
	}
	
	@Override
	public Map<String, Integer> listFlightDurationSum(String dutyCode,DateTimeRange dateTimeRange) {
		Map<String,Integer> map = new HashMap<>();
		
		//从FOC获取数据
		List<FlightInfo> flightInfoList = this.listFlightInfoForCrew(dateTimeRange, null, dutyCode);
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, null);
		
		for(Crew crew : crewList){
			String workcode = crew.getWorkcode();
			int flightDurationSum =  0;
			for(FlightInfo f : flightInfoList){
				String workcodes = f.getCrewWorkcodes();
				if(inWorkcodes(workcodes,workcode)){
					flightDurationSum += f.getFlightDuration();
				}
			}
			map.put(workcode, flightDurationSum);
		}
		return map;
	}
	@Override
	public int flightDutyDurationSum(String dutyCode,DateTimeRange dateTimeRange, String workcode) {
		//获取当前飞行员指定日期范围内的连线
		List<LinkLine> linkLineList = linkLineMapper.listLinkLineBaseByWorkcode(dutyCode,dateTimeRange,workcode);
		
		List<FlightInfo> flightInfoList = flightInfoMapper.listFlightInfoForCrew(dutyCode, dateTimeRange, workcode);
		ListSortUtil.sort(flightInfoList, true, "std");
		//任务环匹配
		taskLoopFlightFactService.flightInfoTaskLoopFlightFactListInit(dutyCode,flightInfoList);
		
		for(LinkLine ll : linkLineList){
			for(FlightInfo f : flightInfoList){
				int crewLinkLineNo = flightInfoService.getCrewLinkLineNo(f, dutyCode);
				if(ll.getFlightDate().equals(f.getFlightDate()) && ll.getCrewLinkLineNo().equals(crewLinkLineNo)){
					ll.getFlightInfoList().add(f);
				}
				
			}
		}
		
		return DutyDurationUtil.flightDutyDurationSum(linkLineList);
	}


	@Override
	public Map<String, Integer> listFlightMoreThanCount(String dutyCode,DateTimeRange dateTimeRange) {
		Map<String,Integer> map = new HashMap<>();
		
		//从FOC获取数据
		List<FlightInfo> flightInfoList = this.listFlightInfoForCrew(dateTimeRange, null,dutyCode);
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, null);
		
		Set<LinkLine> linkLineSet = new HashSet<>();
		
		for(FlightInfo f : flightInfoList){
			LinkLine l  = new LinkLine();
			l.setFlightDate(f.getFlightDate());
			l.setCrewLinkLineNo(f.getCrewLinklineNoF());
			l.setCrewLinkLineKey(MD5Util.md5Encode(l.getFlightDate().toString()+l.getCrewLinkLineNo())); //利用主键，组装Set计划
			linkLineSet.add(l);
		}
		
		//按照每日组装连线
		for(LinkLine l : linkLineSet){
			for(FlightInfo f : flightInfoList){
				if(l.getFlightDate().equals(f.getFlightDate())){
					l.getFlightInfoList().add(f);
				}
			}
		}
		
		//计算每个人的大于3的次数
		for(Crew crew : crewList){
			String workcode = crew.getWorkcode();
			int flightMoreThanFourCount =  0;
			for(LinkLine l : linkLineSet){
				String wrokcodes  = l.getFlightInfoList().get(0).getCrewWorkcodes();
				if(inWorkcodes(wrokcodes,workcode) && l.getFlightInfoList().size()> RuleConstant.FLIGHT_MORE_THAN_COUNT){
					flightMoreThanFourCount ++;
				}
			}
			
			map.put(workcode, flightMoreThanFourCount);
		}
		return map;
	}

	@Override
	public Map<String, Integer> listflightDutyDuration(String dutyCode,DateTimeRange dateTimeRange) {
		Map<String, Integer> map = new HashMap<>();

		// 获取当前飞行员指定日期范围内的连线
		List<LinkLine> linkLineList = linkLineMapper.listLinkLineBaseByWorkcode(dutyCode,dateTimeRange, null);
		ListSortUtil.sort(linkLineList, true, "td");
		
		List<FlightInfo> flightInfoList = flightInfoMapper.listFlightInfoForCrew(dutyCode, dateTimeRange, null);
		ListSortUtil.sort(flightInfoList, true, "std");
		//任务环匹配
		taskLoopFlightFactService.flightInfoTaskLoopFlightFactListInit(dutyCode,flightInfoList);
		
		for(LinkLine ll : linkLineList){
			for(FlightInfo f : flightInfoList){
				int CrewLinklineNo = flightInfoService.getCrewLinkLineNo(f, dutyCode);
				if(ll.getFlightDate().equals(f.getFlightDate()) && ll.getCrewLinkLineNo().equals(CrewLinklineNo)){
					ll.getFlightInfoList().add(f);
				}
			}
		}
			
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, null);
		for (Crew crew : crewList) {
			String workcode = crew.getWorkcode();

			List<LinkLine> linkLineListForCrew = new ArrayList<>();
			for (LinkLine l : linkLineList) {
				String wrokcodes = l.getCrewWorkcodes();
				if (inWorkcodes(wrokcodes, workcode)) {
					linkLineListForCrew.add(l);
				}
			}
			int flightDutyDuration = DutyDurationUtil.flightDutyDurationSum(linkLineListForCrew);
			map.put(workcode, flightDutyDuration);

		}

		return map;

	}
	@Override
	public Map<String, LinkLine> ListLastLinkLine(String dutyCode, Date beforeFlightDate) {
		List<LinkLine>  list = linkLineMapper.listLastLinkLineBase(beforeFlightDate, dutyCode, null);
		Map<String, LinkLine> map = new HashMap<>();
		for(LinkLine l : list){
			String crewLinkLineKey = linkLineService.crewLinkLineKeyInit(l);
			l.setCrewLinkLineKey(crewLinkLineKey);
			map.put(l.getCrewWorkcodes(), l);
		}
		return map;
	}
	@Override
	public Map<String, Integer> nightFlyCount(String dutyCode,DateTimeRange dateTimeRange) {
		Map<String,Integer> map = new HashMap<>();
		
		//从FOC获取数据	
		List<FlightInfo> flightInfoList = flightInfoMapper.listFlightInfoForCrew(dutyCode,dateTimeRange, null);
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, null);
		
		for(Crew crew : crewList){
			String workcode = crew.getWorkcode();
			int nightFlyCount = 0 ;
			for(FlightInfo f : flightInfoList){
				String workcodes = f.getCrewWorkcodes();
				if(inWorkcodes(workcodes,workcode)){
					boolean isnightFly = flightInfoService.isNightFly(f);
					if(isnightFly){
						nightFlyCount ++;
					}
					
				}
			}

			map.put(workcode, nightFlyCount);
		}
		return map;
	}
	@Override
	public Map<String, Integer> badFlightCount(String dutyCode,DateTimeRange dateTimeRange) {
		Map<String,Integer> map = new HashMap<>();
		
		//从FOC获取数据	
		List<FlightInfo> flightInfoList = flightInfoMapper.listFlightInfoForCrew(dutyCode,dateTimeRange, null);
		//任务环初始
		taskLoopFlightFactService.flightInfoTaskLoopFlightFactListInit(dutyCode,flightInfoList);
		
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, null);
		
		for(Crew crew : crewList){
			String workcode = crew.getWorkcode();
			int badFlightCount = 0 ;
			for(FlightInfo f : flightInfoList){
				String workcodes = f.getCrewWorkcodes();
				if(inWorkcodes(workcodes,workcode) && flightInfoService.isBadRouteFlight(f, dutyCode)){
					badFlightCount++;
				}
			}

			map.put(workcode, badFlightCount);
		}
		return map;
	}
	@Override
	public void flightInfoListYearInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRange = this.getFlightDateRangeYear(beforeFlightDate);
		List<FlightInfo> flightInfoList = flightInfoMapper.listFlightInfoForCrew(dutyCode,dateTimeRange, null);
		ListSortUtil.sort(flightInfoList, true, "std");
		
		for(Crew crew : crewList){
			String workcode = crew.getWorkcode();
			for(FlightInfo f : flightInfoList){
				String workcodes = f.getCrewWorkcodes();
				if(inWorkcodes(workcodes,workcode)){
					crew.getCrewFlightExperience().getFlightInfoListYear().add(f);
				}
			}
		}
		
	}
	@Override
	public List<FlightInfo> getFlightInfoListByCrewAndDateTimeRange(List<FlightInfo> crewFlightInfoList,
			DateTimeRange dateTimeRange) {
		DateTime start = new DateTime(dateTimeRange.getStart());
		DateTime end = new DateTime(dateTimeRange.getEnd());
		List<FlightInfo> list = new ArrayList<>();
		for(DateTime temp = start; !temp.isAfter(end) ;temp = temp.plusDays(1)){
			for(FlightInfo f : crewFlightInfoList){
				if(f.getFlightDate().equals(temp.toDate())){
					list.add(f);
				}
			}
		}
		
		return list;
	}
}
